
class BaseDb():

    def format_create_table(self, table, query):
        raise "Subclass Must Inherit"

    def format_change_column(self, table, column_name, attributes):
        return "ALTER TABLE %s MODIFY COLUMN %s %s %s;" \
            % (table, column_name, self._build_column_type(attributes), self._build_remainder(attributes))
            
    def format_add_index(self, table, index_name, query):
        attributes = self._index_build_dictionary(query)
        return "CREATE %s INDEX %s %s ON %s  (%s);" \
            % (self._unique(attributes), index_name, self._using(attributes), table, self._index_build_remainder(attributes))

    def format_add_column(self, table, column_name, attributes):
        return "ALTER TABLE %s ADD %s %s %s;" \
            % (table, column_name, self._build_column_type(attributes), self._build_remainder(attributes))

    def format_rename_column(self, table, column_name, new_name, attributes):
        raise "Subclass Must Inherit"

    def format_rename_table(self, table, new_name):
        return "ALTER TABLE %s RENAME TO %s;" \
            % (table, new_name)

    def format_remove_column(self, table, column_name):
        return "ALTER TABLE %s DROP COLUMN %s;" \
            % (table, column_name)
            
    def _strip_comma(self, desc):
        if desc.strip().endswith(","):
            comma = desc.rfind(",")
            desc = desc[:comma].strip()

        if desc.strip().startswith(","):
            comma = desc.find(",")
            desc = desc[comma + 1:].strip()

        return desc


    def _build_table(self, query):
        columns_string = ""
        table_description = {}
        columns_description = []
        pk_pos = query.find("primary_key:")
        col_pos = query.find("column:")

        if pk_pos < col_pos:
            desc = query[:pk_pos]
            columns_string = query[pk_pos:]
        else:
            desc = query[:col_pos]
            columns_string = query[col_pos:]

        table_description = self._build_table_description(desc)
        primary_key, columns_string = self._build_primary_key(columns_string)
        columns_description = self._build_columns_list(columns_string)

        return table_description, columns_description, primary_key

    def _build_columns_list(self, desc):
        columns = []
        while desc.rfind("column:") >= 0:
            pos = desc.rfind("column:")
            columns.append(desc[pos:].strip())
            desc = self._strip_comma(desc[:pos].strip())

        columns.reverse()
        return columns

    def _build_primary_key(self, desc):
        pk_pos = desc.find("primary_key:")
        col_pos = desc.find("column:")

        primary_key = ""
        primary_string = ""
        column_string = ""

        if pk_pos < col_pos:
            #we only have to cut once
            primary_string = desc[:col_pos]
            column_string = desc[col_pos:]
        else:
            #check to make sure that primary key isn't mixed in
            test_pos = desc.rfind("column:")
            if test_pos > pk_pos:
                #mixed in
                column_string = desc[:pk_pos] + desc[test_pos:]
            else:
                primary_string = desc[pk_pos:]
                column_string = desc[:pk_pos]

        primary_string = self._strip_comma(primary_string)
        column_string = self._strip_comma(column_string)

        primary_key = primary_string.replace("primary_key:", "").strip()
        return primary_key, column_string

    def _columns(self, columns):
        string = ""

        count = 0
        for element in columns:
            column_name, element = self._column_name(element)
            if count == 0:
                string = "%s %s" % (column_name, self._format_attributes(element))
                count = 1
            else:
                string = "%s,%s %s" % (string, column_name, self._format_attributes(element))

        string = self._strip_comma(string)

        return string.strip()


    def _format_attributes(self, desc):
        attribute_dict = self._build_dictionary(desc)
        column_type = self._build_column_type(attribute_dict)
        remainder_string = self._build_remainder(attribute_dict)
        return "%s %s" \
            % (column_type, remainder_string)

    def _build_table_description(self, desc):
        desc = self._strip_comma(desc)
        attributes = {}
        elements = desc.split(",")
        for element in elements:
            attribute = element.split(":")
            attributes[attribute[0].lower().strip()] = attribute[1].strip()

        return attributes

    def _primary_key(self, primary_key):
        if not primary_key == "":
            return ", PRIMARY KEY (%s)" % primary_key
        else:
            return ""

    def _comment(self, attributes):
        if 'comment' in attributes:
            return "COMMENT = '%s'" % attributes['comment']
        else:
            return ""

    def _column_name(self, desc):
        comma = desc.find(",")
        name = desc[:comma].replace("column:", "").strip()
        return self._strip_comma(name), self._strip_comma(desc[comma:])

    def _build_dictionary(self, query):
        attributes = {}
        elements = query.split(",")
        for element in elements:
            attribute = element.split(":")
            attributes[attribute[0].lower().strip()] = attribute[1].strip()

        return attributes
    #----------------


    def _build_column_type(self, attributes):
        type = attributes['type'].upper()

        if 'length' in attributes:
            type = "%s(%s" % (type, attributes['length'])

            if 'precision' in attributes:
                type = "%s,%s)" % (type, attributes['precision'])
            else:
                type = "%s)" % type

        return type

    def _unique(self, attributes):
        if 'unique' in attributes and attributes['unique'].lower() == "true":
            return "UNIQUE"
        return ""

    def _engine(self, attributes):
        return ""

    def _char_set(self, attributes):
        return ""

    def _using(self, attributes):
        return ""

    def _index_build_dictionary(self, query):
        attributes = {}
        #first remove the column names from the query
        start = query.find("[")
        end = query.rfind("]")
        columns = query[start + 1:end]
        new_query = query[:start] + query[end + 1:]
        elements = new_query.split(",")
        for element in elements:
            attribute = element.split(":")
            attributes[attribute[0].lower().strip()] = attribute[1].strip()

        attributes['columns'] = self._index_column_build(columns)

        return attributes

    def _index_column_build(self, columns):
        listing = []
        new_columns = columns.split(",")
        for i in range(len(new_columns)):
            new_columns[i] = new_columns[i].strip()
        for column in new_columns:
            elements = column.split(" ")
            elements[0] = elements[0].replace("`", "")
            elements[0] = elements[0].replace("'", "")
            if len(elements) == 1:
                listing.append(elements[0].strip())
            else:
                listing.append(elements[0].strip() + " " + elements[1].strip())

        return listing

    def _index_build_remainder(self, attributes):
        string = ""
        count = 0
        for column in attributes['columns']:
            if count > 0:
                string = "%s,%s" % (string,column)
            else:
                count = 1
                string = column


        return string